"""ADC models which generate various sorts of random data.

Copyright (C) Sarah Mount, 2008.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
"""

from __future__ import absolute_import
del absolute_import
from .. import ADCModel
import random, threading

class ADCRandomUniform(ADCModel.ADCModel):
    """ADC model supplying uniformally random data."""
    def __init__(self, low=-1, high=1):
        """
        @precondition: low < high
        @type low: int
        @param low: lower bound of Uniform distribution
        @type high: int
        @param high: upper bound of Uniform distribution
        """
        ADCModel.ADCModel.__init__(self)
        self.name = 'Random Uniform'
        self.rand = random.Random()
        self.low = low
        self.high = high
        return
    def setLow(self, low):
        self.low = low
        return
    def setHigh(self, high):
        self.high = high
        return
    def getPointData(self, vector=1, transducer=None):
        data = [self.rand.uniform(self.low, self.high) for r in range(vector)]
        return (None, data)
    

class ADCRandomGauss(ADCModel.ADCModel):
    """ADC model supplying random data from a Gaussian distribution."""
    def __init__(self, mu=0, sigma=1):
        """        
        @type mu: float
        @param mu: mean of the Gaussian distribution to sample from
        @type sigma: float
        @param sigma: variance of the Gaussian distribution to sample from
        """
        ADCModel.ADCModel.__init__(self)
        self.name = 'Random Gaussian'
        self.rand = random.Random()
        self.rand_l = threading.Lock
        """@ivar: lock for the random number generator. C{gauss} is not thread-safe."""
        self.mu = mu
        """@ivar: mean of the Gaussian distribution to sample from"""
        self.sigma = sigma
        """@ivar: variance of the Gaussian distribution to sample from"""
        return
    def setMu(self, mu):
        self.mu = mu
        return
    def setSigma(self, sigma):
        self.sigma = sigma
    def getPointData(self, vector=1, transducer=None):
        self.rand_l.acquire()
        data = [self.rand.gauss(self.mu, self.sigma) for r in range(vector)]
        self.rand_l.release()
        return (None, data)


class ADCRandomSelection(ADCModel.ADCModel):
    """ADC model supplying data from a known sequence.
    Useful in situations where the data returned from a transducer can
    only take a known set of discrete values -- for example a switch.
    """
    def __init__(self, values=[]):
        """        
        @type values: sequence
        @param values: possible values that can be returned by the transducer
        """
        ADCModel.ADCModel.__init__(self)
        self.name = 'Random Sequence Selection'        
        self.rand = random.Random()
        self.rand_l = threading.Lock
        """@ivar: lock for the random number generator"""
        self.values = values
        """@ivar: set of values that can be returned by the transducer"""
        return
    def setValues(self, values):
        self.values = values
        return
    def getPointData(self, vector=1, transducer=None):
        self.rand_l.acquire()
        data = [self.rand.choice(self.values) for r in range(vector)]
        self.rand_l.release()
        return (None, data)


adcRandomUniform   = ADCRandomUniform()
adcRandomGauss     = ADCRandomGauss()
adcRandomSelection = ADCRandomSelection()
